<?php 
abstract class BaseVkontakte
{
  private $apiUrl = 'https://api.vk.com/method/';
  /**
   * The Application ID.
   */
  protected $appId;

  /**
   * The Application API Secret.
   */
  protected $apiSecret;

  protected $user;

  /**
   * The OAuth access token received in exchange for a valid authorization
   * code.  null means the access token has yet to be determined.
   */
  protected $accessToken = null;
	
  /**
	 * @return the $apiUrl
	 */
	public function getApiUrl() {
		return $this->apiUrl;
	}

/**
	 * @return the $appId
	 */
	public function getAppId() {
		return $this->appId;
	}

/**
	 * @return the $apiSecret
	 */
	public function getApiSecret() {
		return $this->apiSecret;
	}

/**
	 * @return the $accessToken
	 */
	public function getAccessToken() {
		return $this->accessToken;
	}

/**
	 * @param field_type $apiUrl
	 */
	public function setApiUrl($apiUrl) {
		$this->apiUrl = $apiUrl;
}

/**
	 * @param field_type $appId
	 */
	public function setAppId($appId) {
		$this->appId = $appId;
	}

/**
	 * @param field_type $apiSecret
	 */
	public function setApiSecret($apiSecret) {
		$this->apiSecret = $apiSecret;
	}

/**
	 * @param field_type $user
	 */
	public function setUser($user) {
		$this->user = $user;
	}

/**
	 * @param field_type $accessToken
	 */
	public function setAccessToken($accessToken) {
		$this->accessToken = $accessToken;
	}

public function __construct($config) {
    $this->setAppId($config['appId']);
    $this->setApiSecret($config['secret']);
  }
	
  
  
 /**
   * Get the UID of the connected user, or 0
   * if the Facebook user is not connected.
   *
   * @return String the UID if available.
   */
  public function getUser() {
    if ($this->user !== null) {
      // we've already determined this and cached the value.
      return $this->user;
    }

    return $this->user = $this->getUserFromAvailableData();
  }

  /**
   * Determines the connected user by first examining any signed
   * requests, then considering an authorization code, and then
   * falling back to any persistent store storing the user.
   *
   * @return Integer the id of the connected Facebook user, or 0
   * if no such user exists.
   */
  protected function getUserFromAvailableData() {
    $user = $this->getPersistentData('user_id', $default = 0);
	if (!$user) {
			$code = null;
			if (isset($_SESSION['code'])) {
				$code = $_SESSION['code'];
			}

			if (isset($_GET['code'])) {
				$code = $_GET['code'];
			}

			if ($code) {
				// get access token
				$query = 'https://api.vkontakte.ru/oauth/access_token?client_id=' . $this->appId . '&client_secret=' . $this->apiSecret . '&code=' . $code;
                		$res = file_get_contents($query);
		                $res = json_decode($res, true);
				$this->setPersistentData('access_token', $res['access_token']);
				$this->setPersistentData('user_id', $res['user_id']);
				return $this->getPersistentData('user_id');
			}
	}
    return $user;
  }

  /**
   * Get a Login URL for use with redirects. By default, full page redirect is
   * assumed. If you are using the generated URL with a window.open() call in
   * JavaScript, you can pass in display=popup as part of the $params.
   *
   * The parameters:
   * - redirect_uri: the url to go to after a successful login
   * - scope: comma separated list of requested extended perms
   *
   * @param Array $params provide custom parameters
   * @return String the URL for the login flow
   */
  public function getLoginUrl($scope = 'wall') {
  		$params = array('client_id' => $this->getAppId(),
  						'scope' => $scope,
  						'redirect_uri' => $this->getCurrentUrl(),
  						'display' => 'page',
  						'response_type' => 'code');
  						
  		$url = 'http://api.vkontakte.ru/oauth/authorize?' . http_build_query($params, null, '&');
  		return $url;
  }

  /**
   * Get a Logout URL suitable for use with redirects.
   *
   * The parameters:
   * - next: the url to go to after a successful logout
   *
   * @param Array $params provide custom parameters
   * @return String the URL for the logout flow
   */
  public function getLogoutUrl($params=array()) {
		return '';    
  }
  
  protected function getCurrentUrl() {
    $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on'
      ? 'https://'
      : 'http://';
    $currentUrl = $protocol . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
    $parts = parse_url($currentUrl);

    $query = '';
    if (!empty($parts['query'])) {
      // drop known fb params
      $params = explode('&', $parts['query']);
      $retained_params = array();

      if (!empty($retained_params)) {
        $query = '?'.implode($retained_params, '&');
      }
    }

    // use port if non default
    $port =
      isset($parts['port']) &&
      (($protocol === 'http://' && $parts['port'] !== 80) ||
       ($protocol === 'https://' && $parts['port'] !== 443))
      ? ':' . $parts['port'] : '';

    // rebuild
    return $protocol . $parts['host'] . $port . $parts['path'] . $query;
  }
  
  
  public function api(/* polymorphic */) {
    $args = func_get_args();
      return call_user_func_array(array($this, '_api'), $args);
  }
  
	function _api($method,$params=false) {
		if (!$params) $params = array(); 
		$query = $this->apiUrl. $method . '?'.$this->params($params) . '&access_token=' . $this->getPersistentData('access_token');
		$res = file_get_contents($query);
		$res = json_decode($res, true);
		if (isset($res['error'])) {
			if ($res['error']['error_code'] == 14) {
				return $res['error'];
			}
			throw new Exception($res['error']['error_msg']);
		}
		return $res['response'];
	}
	
	function params($params) {
		$pice = array();
		foreach($params as $k=>$v) {
			$pice[] = $k.'='.urlencode($v);
		}
		return implode('&',$pice);
	}
	
  abstract public function setPersistentData($key, $value);
  abstract protected function getPersistentData($key, $default = false);
  abstract protected function clearPersistentData($key);
  abstract protected function clearAllPersistentData();
}
